import axios from 'axios'
import Validator from 'async-validator'
import assign from './utils/assign'
import urlQuery from './utils/url-query'
import cookie from './utils/cookie'
import * as base64 from './utils/base64'
import { v1 as uuid } from 'uuid'
import dateFormat from './utils/dateformat'
import downloadFile2 from './utils/download2'
import * as arr from './utils/arr'
import * as tree from './utils/tree'
import * as file from './utils/file'
import * as el from './utils/el'
import * as event from './utils/event'
import XYChanger from './utils/xyChanger'
import toRemPx from './utils/toRemPx'
import genError from './utils/gen-error'
import cloneJson from './utils/clone-json'
import { shake } from './utils/shake'
import extToFileType from './utils/extToFileType'
import getFilenameFromUrl from './utils/get-filename-from-url'
import numToPercent from './utils/num-to-percent'
import numToLetter from './utils/num-to-letter'
import numToNumber from './utils/num-to-number'
import numToRoman from './utils/num-to-roman'
import numToChinese from './utils/num-to-chinese'
import validateEditorIsNull from './utils/validateEditorIsNull'
import client from './utils/client'
import * as generateArray from './utils/generateArray'
import mimetype from './utils/mime-type'
import qs from 'qs';
import CryptoJS from 'crypto-js';

let utf8 = CryptoJS.utf8
let aes = CryptoJS.aes
let pkcs7 = CryptoJS.pkcs7
let ecb = CryptoJS.mode.ECB
let crypto = {
  enc: {
    Utf8: utf8
  },
  AES: aes,
  mode: {
    ECB: ecb
  },
  pad: {
    Pkcs7: pkcs7
  }
}
const storagePrifixKey = 'zn_abc'
export const UiUtils = {
  install(app, options) {
    // console.log('install', options)
    let t0 = 0
    let wait = options ? parseInt(options.wait) : 3000

    let utils = {
      // get unix timestamp
      get now () {
        return Date.now()
      },

      get getServeTime () {
        return new Promise((resolve, reject) => {
          let request = new XMLHttpRequest()
          request.open('HEAD', window.location.href.toString(), false)

          request.onreadystatechange = function () {
            if (request.readyState === 4) {
              if ((request.status >= 200 && request.status < 300) || request.status === 304) {
                resolve(new Date(request.getResponseHeader('Date')))
              } else {
                reject(new Error('Failed to get serve time.'))
              }
            }
          }

          request.setRequestHeader('Content-Type', 'text/html')
          request.send(null)
        })
      },

      get urlQuery () {
        return urlQuery()
      },

      // debounce click
      get debounceExpired () {
        let t1 = new Date().getTime()

        if (t1 - t0 > wait) {
          t0 = t1
          return true
        } else {
          return false
        }
      },

      setDefaultHeaders (header) {
        Object.assign(axios.defaults.headers.common, shake(header, [undefined, null]))
      },

      CryptoJS: {
        ...crypto
      },
      /****
      * 查找是否引入某个资源并删除
      */
      searchImportResAndRemove (name) {
        var js = /js$/i.test(name)
        var es = document.getElementsByTagName(js ? 'script' : 'link')
        let flag = false
        for (var i = 0; i < es.length; i++) {
          if (es[i][js ? 'src' : 'href'].indexOf(name) !== -1) {
            es[i].parentNode.removeChild(es[i])
            break
          }
        }
        return flag
      },
      /****
       * 上传图片通过原生方法
       *  * @param {Type} option 上传选项
       *  * |- uploadUrl 服务器上传文件的url地址
        *   |- data 数据本身
        *   |- filename 文件名
        *   |- mimeType mimeType类型
        *   |- extendData 上传时额外的数据
        *   |- onUploadProgress 记录上传进度的回调函数
        *   |- axiosSource axios的取消token源
      */
      uploadFileWithAjax (option) {
        let formData = new FormData()
        let extendData = Object.assign({}, option.extendData)
        for (const [key, value] of Object.entries(extendData)) {
          formData.append(key, value)
        }
        formData.append('file', option.data, option.filename)

        let axiosOption = {
          method: 'post',
          url: option.uploadUrl,
          data: formData,
          timeout: 30000,
          headers: {
            'Content-Type': 'multipart/form-data',
            'branchCode': option.headers.branchCode || window.$app.user.branchCode
          },

          onUploadProgress (event) {
            if (event.lengthComputable && typeof option.onUploadProgress === 'function') {
              option.onUploadProgress(option, event.loaded, event.total)
            }
          }
        }

        if (option.axiosSource) {
          axiosOption.cancelToken = option.axiosSource.token
        }

        return axios(axiosOption).then(res => {
          return res
        }).catch(e => {
          return Promise.reject(e)
        })
      },
      /***
       * 动态加载js
       */
      loadJs (url, callback) {
        this.searchImportResAndRemove(url)
        let script = document.createElement('script')
        let fn = callback || function () { }
        script.type = 'text/javascript'
        // IE
        if (script.readyState) {
          script.onreadystatechange = function () {
            if (script.readyState === 'loaded' || script.readyState === 'complete') {
              script.onreadystatechange = null
              fn()
            }
          }
        } else {
          // 其他浏览器
          script.onload = function () {
            fn()
          }
        }
        script.src = url
        document.getElementsByTagName('head')[0].appendChild(script)
      },

      /****
       * 动态引入css文件
       */
      loadCSS (url) {
        if (this.searchImportRes(url)) {
          return
        }
        let head = document.getElementsByTagName('head')[0]
        let link = document.createElement('link')
        link.rel = 'stylesheet'
        link.href = url
        link.type = 'text/css'
        head.appendChild(link)
      },

      /****
       * 查找是否引入某个资源
      */
      searchImportRes (name) {
        var js = /js$/i.test(name)
        var es = document.getElementsByTagName(js ? 'script' : 'link')
        let flag = false
        for (var i = 0; i < es.length; i++) {
          if (es[i][js ? 'src' : 'href'].indexOf(name) !== -1) {
            flag = true
            break
          }
        }
        return flag
      },

      // 加密
      toEncryption (value) {
        const key = CryptoJS.enc.Utf8.parse(window.$app.appKey)
        return CryptoJS.AES.encrypt(value, key, {
          mode: CryptoJS.mode.ECB,
          padding: CryptoJS.pad.Pkcs7
        }).toString()
      },

      // 解密
      toDecrypt (value) {
        const key = CryptoJS.enc.Utf8.parse(window.$app.appKey)
        return CryptoJS.AES.decrypt(value, key, {
          mode: CryptoJS.mode.ECB,
          padding: CryptoJS.pad.Pkcs7
        }).toString(CryptoJS.enc.Utf8)
      },

      openWin (url, target) {
        if (!target) {
          target = '_blank'
        }
      
        if (target === '_blank') {
          window.open(url, target)
        } else {
          window.location.href = url
        }
      },
      local: {
        get(key) {
          key = `${storagePrifixKey}_${key}`
          let value = window.localStorage.getItem(key)
    
          try {
            const result = JSON.parse(window.localStorage.getItem(key))
    
            if (typeof result === 'object') {
              value = result
            }
          } catch (e) {
            // noop
          }
    
          return value
        },
    
        set(key, value) {
          key = `${storagePrifixKey}_${key}`
    
          if (typeof value === 'object') {
            value = JSON.stringify(value)
          }
    
          window.localStorage.setItem(key, value)
        },
    
        remove(key) {
          key = `${storagePrifixKey}_${key}`
          window.localStorage.removeItem(key)
        },
    
        clear(appURI) {
          if (appURI) {
            const matchedKeys = Object.keys().filter(function (key) {
              return key.indexOf(appURI) > -1
            })
    
            for (const key of matchedKeys) {
              window.localStorage.removeItem(key)
            }
          } else {
            window.localStorage.clear()
          }
        }
      },
      qs,
      arr,
      tree,
      el,
      file,
      event,
      mimetype,
      XYChanger,
      assign,
      cookie,
      base64: {
        ...base64
      },
      noop () { },
      uuid,
      dateFormat,
      downloadFile2,
      toRemPx,
      genError,
      cloneJson,
      extToFileType,
      getFilenameFromUrl,
      client,
      numToPercent,
      numToLetter,
      numToChinese,
      validateEditorIsNull,
      Validator,
      numToRoman,
      numToNumber,
      ...options,
      ...generateArray
    }

    Object.freeze(utils)

    window.$ui = utils
    // console.log('$ui', window.$ui)
    app.config.globalProperties.$ui = window.$ui
    app.config.globalProperties.$noop = utils.noop
  }
}
